package de.mhu.mandalaui;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import de.mhu.mandalaui.actions.SequenceAction;
import de.mhu.mandalaui.bind.Element;
import de.mhu.mandalaui.remote.RemoteCallable;
import de.mhu.mandalaui.remote.RemoteRegistry;

public abstract class Window extends Component {

	private Component content = null;
	private long nextId = 0;
	private SequenceAction initialAction = new SequenceAction();
	private LinkedList<Element> registry = new LinkedList<Element>();
	private Ui ui;
	private HashMap<String, RemoteRegistry> remoteRegistry = new HashMap<String, RemoteRegistry>();

	public Window(Ui ui, String id) {
		this.ui = ui;
		setId(id);
	}
	
	public Component getContent() {
		return content;
	}

	public void setContent(Component content) {
		if (this.content != null) this.content.componentDetach();
		this.content = content;
		content.componentAttach(this);
	}
	
	public abstract void doRender(Object ... attributes) throws Exception;
	
	public void render(Response response) {
		
		initialAction.setOwner(this);
		response.registerAttribute(initialAction);
		initialAction.startRender(response);
		
		for (Element a : registry) {
			a.setOwner(this);
			response.registerAttribute(a);
		}
		response.containerEnter(this);
		if (content != null) {
			response.containerEnter(content);
			content.render(response);
			response.containerLeave();
		}
		response.containerLeave();
	}

	public String nextId() {
		return "a" + (++nextId);
	}
	
	public Window getWindow() {
		return this;
	}

	public SequenceAction getInitialAction() {
		return initialAction;
	}
	
	public List<Element> getRegistry() {
		return registry;
	}

	public Ui getUi() {
		return ui;
	}

	public RemoteRegistry registerRemoteCall(RemoteCallable ds) {
		synchronized (remoteRegistry) {
			RemoteRegistry remote = remoteRegistry.get(ds.getId());
			if (remote == null) {
				remote = new RemoteRegistry(this,ds);
				remoteRegistry.put(ds.getId(), remote);
			}
			return remote;
		}
	}

	public abstract String getRemoteUrl(RemoteRegistry registry);

	public synchronized void close() {
		if (ui == null) return;
		ui.remove(this);
		ui = null;
	}

	public RemoteRegistry getRemote(String id) {
		synchronized (remoteRegistry) {
			return remoteRegistry.get(id);
		}
	}

}
